﻿using HeHe;
using InfonavaEye.handler;
using InfonavaEye.model;
using InfonavaEye.util;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace InfonavaEye.common
{
    public class FormDataBridge
    {
        public static int rowNum = 0;
        public static List<OCRResult> OCRDataList = new List<OCRResult>();
        public static Dictionary<string, OCRResult> OCRDataDic = new Dictionary<string, OCRResult>();

        public static List<Task> taskList = new List<Task>();
        private static TaskFactory taskFactory = new TaskFactory(new LimitedTaskScheduler(Environment.ProcessorCount));
        private static bool taskRolling = false;

        static HeHeOcr heheOcr = new HeHeOcr();
        public delegate void ImageOCRDelegate(OCRResult result);
        public static event ImageOCRDelegate receiveOCRResult;

        public static event Action<OCRResult> appendResultDelegate;

        public delegate void UpdateResultDelegate(OCRResult result);
        public static event UpdateResultDelegate updateResultDelegate;

        public delegate void RemoveResultDelegate(OCRResult result);
        public static event RemoveResultDelegate removeResultDelegate;

        //再次拉直回调
        public delegate void ReStraightenDelegate(OCRResult result);
        public static event ReStraightenDelegate reStraightenDelegate;

        //再次处理回调
        public delegate void RedoDelegate(OCRResult result);
        public static event RedoDelegate redoDelegate;


        //暂停
        public delegate void PauseRunAutoCaptureDelegate();
        public static event PauseRunAutoCaptureDelegate pauseRunAutoCaptureDelegate;



        //定位窗口完成重新拍照之后更新按钮 状态
        public delegate void CameraPreviewDoneDelegate();
        public static event CameraPreviewDoneDelegate cameraPreviewDoneDelegate;


        public static string captureOptSN;

        public static string DEFAULT_CODE = "识别中....";

        public static OCRResult odlImageOCrResult;

        /// <summary>
        /// 自动抓拍的钉子
        /// </summary>
        public static Queue<Nail> autoCaptureNailQueue = new Queue<Nail>();

        public static void clearAutoCaptureNailQueue() {
            autoCaptureNailQueue.Clear();
        }

        public static void appendOCRTask(string fileFullPath, int shape, bool isSample) {
            appendOCRTask(fileFullPath, shape, isSample, false);
        }

        /// <summary>
        /// OCR识别完毕，推送到list界面
        /// </summary>
        /// <param name="fileFullPath"></param>
        /// <param name="shape"> 形状 1 线型，2 圆型</param>
        /// <param name="isSample">仅采样不拉直</param>
        public static void appendOCRTask(string fileFullPath, int shape, bool isSample, bool twirl180 = false)
        {
            if (odlImageOCrResult != null)
            {
               
                var index = OCRDataList.FindIndex(p => p.rowNum == odlImageOCrResult.rowNum);
                if (index > -1)
                {
                    var result = OCRDataList[index];
                    result.code = "识别中...";
                    result.filePath = fileFullPath;
                    result.status = 2;
                    OCRDataDic[result.filePath] = result;
                    taskFactory.StartNew(OCRWork, result);
                }
                odlImageOCrResult = null;
                FormDataBridge.cameraPreviewDoneDelegate.Invoke();
            }
            else
            {
                rowNum++;
                Nail nail = null;
                if (autoCaptureNailQueue.Count > 0)
                {
                    nail = autoCaptureNailQueue.Dequeue();
                };
             
                var result = new OCRResult()
                {
                    nail = nail,
                    rowNum = rowNum,
                    code = DEFAULT_CODE,
                    // NailShape (1.脊柱钉类, 2.创伤圆钉类  3.板棒类)
                    shape = nail != null ? (nail.boxModel.NailShape == 2 ? 2 : 1) : shape,
                    filePath = fileFullPath,
                    isSample = isSample,
                };
                if (nail == null && twirl180)
                {
                    nail = new Nail();
                    BoxArea tmpBoxArea = new BoxArea();
                    tmpBoxArea.twirl180 = twirl180;
                    nail.area = tmpBoxArea;
                    result.nail= nail;
                }

                OCRDataDic.Add(result.filePath, result);
                OCRDataList.Add(result);

                if (appendResultDelegate != null)
                {
                    appendResultDelegate.Invoke(result);
                }
                taskFactory.StartNew(OCRWork, result);
            }
        }
 

        private static void RollTask()
        {
            if (!taskRolling)
            {
                Thread taskThread = new Thread(new ThreadStart(RunTask));
                taskThread.Start();
                taskRolling = true;
            }
        }

        private static void RunTask()
        {
            while (true)
            {
                if (taskList.Count > 0)
                {
                    try
                    {
                        Task task = taskList[0];
                        task.Start();
                        task.Wait();
                        taskList.RemoveAt(0);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("执行OCR识别任务时发生异常 ，{0},{1}", ex.Message, ex.StackTrace);
                    }
                }
                else
                {
                    Thread.Sleep(300);
                }
            }
        }

        /// <summary>
        /// 删除数据
        /// </summary>
        /// <param name="fileFullPath"></param>
        public static void removeOCRResult(string fileFullPath)
        {
            if (fileFullPath == null)
            {
                return;
            }

            if (OCRDataDic.ContainsKey(fileFullPath))
            {
                var result = OCRDataDic[fileFullPath];
                OCRDataList.Remove(result);
                if (removeResultDelegate != null)
                {
                    removeResultDelegate.Invoke(result);
                }

                OCRDataDic.Remove(fileFullPath);
                rowNum--;
            }
        }

        public static void removeAt(int rowNum)
        {
            if (OCRDataList.Count - 1 >= rowNum)
            {
                OCRDataDic.Remove(OCRDataList[rowNum].filePath);
                OCRDataList.RemoveAt(rowNum);
            }
        }

        public static void UpdateItemCode(int rowNum, string code)
        {
            var index = OCRDataList.FindIndex(p => p.rowNum == rowNum);
            if (index > -1)
            {
                var result = OCRDataList[index];
                result.code = code;
                OCRDataDic[result.filePath] = result;
            }
        }

        /// <summary>
        /// 识别
        /// </summary>
        /// <param name="data"></param>
        static void doOCR(object data)
        {
            OCRResult result = data as OCRResult;
            if (result == null)
            {
                return;
            }

            try
            {
                var startTime = DateTime.Now;
                Console.WriteLine("{0} 正在OCR识别，filePath={1}", startTime, result.filePath);
                if (result.shape == (int)ImageShapeEnum.CIRCLE)
                {
                    if (!result.isSample)
                    {
                        if (!String.IsNullOrEmpty(result.straightFilePath) && result.straightFilePath.EndsWith(".jpg"))
                        {
                            result.code = heheOcr.Recognize(result.straightFilePath, (int)ImageShapeEnum.CIRCLE);
                            Console.WriteLine("{0} 新算法 OCR识别完成，结果：{1},用时：{2}, filePath={3}",
                            DateTime.Now, result.code, DateTime.Now - startTime, result.filePath);
                        }
                        else
                        {
                            result.code = "识别失败";
                        }

                        if (!String.IsNullOrEmpty(result.straightFilePathOld) && result.straightFilePathOld.EndsWith(".jpg"))
                        {
                            result.codeOld = heheOcr.Recognize(result.straightFilePathOld, (int)ImageShapeEnum.CIRCLE);
                            Console.WriteLine("{0} 旧算法 OCR识别完成，结果：{1},用时：{2}, filePath={3}",
                            DateTime.Now, result.code, DateTime.Now - startTime, result.filePath);
                        }
                        else
                        {
                            result.codeOld = "识别失败";
                        }
                    }
                    else
                    {
                        result.code = "仅采样";
                        result.codeOld = "仅采样";
                    }

                    if (receiveOCRResult != null)
                    {
                        receiveOCRResult.Invoke(result);
                    }

                    //再次拉直
                    if (result.status == 2)
                    {
                        result.status = 1;
                        if (reStraightenDelegate != null)
                        {
                            reStraightenDelegate.Invoke(result);
                        }
                    }
                    //重新处理
                    else if (result.status == 3)
                    {
                        result.status = 1;
                        if (redoDelegate != null)
                        {
                            redoDelegate.Invoke(result);
                        }
                    }
                }
                else if (result.shape == (int)ImageShapeEnum.RECTANGLE)
                {
                    //长方形的物品，直接识别
                    if (!result.isSample)
                    {
                        result.code = heheOcr.Recognize(result.filePath, (int)ImageShapeEnum.RECTANGLE);
                    }
                    else
                    {
                        result.code = "仅采样";
                    }

                    if (receiveOCRResult != null)
                    {
                        receiveOCRResult.Invoke(result);
                    }

                    //重新处理
                    if (result.status == 3)
                    {
                        result.status = 1;
                        if (redoDelegate != null)
                        {
                            redoDelegate.Invoke(result);
                        }
                    }
                }
                if (updateResultDelegate != null)
                {
                    updateResultDelegate.Invoke(result);
                }
            }
            catch (OCRNetException ex) {
                //OCR网络异常停止拍照
                if (pauseRunAutoCaptureDelegate!=null) {
                    pauseRunAutoCaptureDelegate.Invoke();
                }

            }
            catch (Exception ex)
            {
                Console.WriteLine("OCR识别时发生异常：{0} {1}", ex.Message, ex.StackTrace);
                result.code = "ERROR";
            }
        }


        /// <summary>
        /// 拉直
        /// </summary>
        /// <param name="data"></param>
        static void doStraight(object data)
        {
            OCRResult result = data as OCRResult;
            if (result == null)
            {
                return;
            }
          
            if (Eps.Ai.Common.Config.OCR_MODEL== (int)OCRModelEnum.LOCALSTRAIGHT) {
                LocalStraight(result);
                return;
            }

            if (Eps.Ai.Common.Config.OCR_MODEL == (int)OCRModelEnum.SERVER)
            {
                //先将图片上传到服务器，然后再服务器拉直
               OCRAndStraightService.captrueDoneDelegate -= null;
               OCRAndStraightService.Instance.uploadStraightOdlImg(result,captureOptSN, autoCaptureNailQueue.Count);
                return;
            }


        }
      public static void receiveServerOCRResult(OCRResult result)
        {
            var index = OCRDataList.FindIndex(p => p.rowNum == result.rowNum);
            if (index > -1)
            {
                OCRDataList[index].code= result.code;
                OCRDataList[index].straightFilePath=result.straightFilePath;
            }
            //重新处理
            if (result.status == 3)
            {
                result.status = 1;
                if (redoDelegate != null)
                {
                    redoDelegate.Invoke(result);
                }
            }
            if (receiveOCRResult != null)
            {
                receiveOCRResult.Invoke(result);
            }
            if (updateResultDelegate != null)
            {
                updateResultDelegate.Invoke(result);
            }
         
        }
        /// <summary>
        /// 
        /// 设备本地拉直 ocr  //圆型的物品先拉直，后识别
        /// </summary>
        /// <param name="result"></param>
        static void LocalStraight(OCRResult result)
        {
            try
            {
                var startTime = DateTime.Now;
                Console.WriteLine("{0} 正在拉直，filePath={1}", startTime, result.filePath);
                if (result.shape == (int)ImageShapeEnum.CIRCLE)
                {
                    //luoxuebo 20230826  新拉直算法
                    int iRotateAngle = 0;
                    if (result.nail!=null&& result.nail.area!=null&&result.nail.area.twirl180) {
                        iRotateAngle = 180;
                    }
                    string straightImagePath = StraightHelper.straight(result.filePath, iRotateAngle);
                    //新算法
                   // string straightImagePath = StraightHelper.Straight2(result.filePath);
                    Console.WriteLine("{0} 新算法 拉直完成,用时：{1}", DateTime.Now, DateTime.Now - startTime);
                    if (straightImagePath.EndsWith(".jpg"))
                    {
                        result.straightFilePath = straightImagePath;
                    }
                    else
                    {
                        result.errorMsg = straightImagePath;
                    }


                    if (receiveOCRResult != null)
                    {
                        receiveOCRResult.Invoke(result);
                    }
                    //拉直完成后，进行OCR识别
                    taskFactory.StartNew(doOCR, result);

                    if (result.status == 2)
                    {
                        result.status = 1;
                        if (reStraightenDelegate != null)
                        {
                            reStraightenDelegate.Invoke(result);
                        }
                    }
                }

                if (updateResultDelegate != null)
                {
                    updateResultDelegate.Invoke(result);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("拉直时发生异常：{0} {1}", ex.Message, ex.StackTrace);
                result.code = "ERROR";
            }

        }

        static void OCRWork(object data)
        {
            OCRResult result = data as OCRResult;
            if (result == null)
            {
                return;
            }
         
            if (result.shape == (int)ImageShapeEnum.CIRCLE)
            {
                taskFactory.StartNew(doStraight, result);
            }
            else
            {
               
                if (Eps.Ai.Common.Config.OCR_MODEL == (int)OCRModelEnum.LOCALSTRAIGHT) {
                    taskFactory.StartNew(doOCR, result);
                    return;
                }
                if (Eps.Ai.Common.Config.OCR_MODEL == (int)OCRModelEnum.SERVER)
                {
                    //先将图片上传到服务器，然后再服务器拉直
                    OCRAndStraightService.captrueDoneDelegate -= null;
                    OCRAndStraightService.Instance.uploadStraightOdlImg(result, captureOptSN, autoCaptureNailQueue.Count);
                    return;
                }
            }
        }

        /*static void OCRWork(object data)
        {
            OCRResult result = data as OCRResult;
            if (result == null)
            {
                return;
            }

            try
            {
                var startTime = DateTime.Now;
                Console.WriteLine("{0} 正在OCR识别，filePath={1}", startTime, result.filePath);
                if (result.shape == (int)ImageShapeEnum.CIRCLE)
                {
                    //圆型的物品先拉直，后识别
                    string straightImagePath = StraightHelper.Straight(result.filePath);
                    Console.WriteLine("{0} 拉直完成,用时：{1}", DateTime.Now, DateTime.Now - startTime);
                    if (straightImagePath.IndexOf("socket_multi_process_server") == -1)
                    {
                        IntPtr strPath = Marshal.StringToHGlobalAnsi(System.Environment.CurrentDirectory);
                        var baseDir = Marshal.PtrToStringAnsi(strPath);
                        straightImagePath = baseDir + "\\img" + straightImagePath.Substring(straightImagePath.LastIndexOf("\\"));
                    }

                    if (straightImagePath != null && straightImagePath.EndsWith(".jpg"))
                    {
                        string newFilePath = result.filePath.Replace(".jpg", "_s.jpg");
                        if (!File.Exists(newFilePath))
                        {
                            File.Copy(straightImagePath, newFilePath, true);
                        }
                        result.straightFilePath = newFilePath;
                        if (!result.isSample) {
                            result.code = heheOcr.Recognize(newFilePath, (int)ImageShapeEnum.CIRCLE);
                        }
                        if (receiveOCRResult != null)
                        {
                            receiveOCRResult.Invoke(result);
                        }
                    }
                    if (result.status==2)
                    {
                        result.status = 1;
                        if (reStraightenDelegate!=null) {
                            reStraightenDelegate.Invoke(result);
                        }
                    }
                }
                else if (result.shape == (int)ImageShapeEnum.RECTANGLE)
                {
                    //长方形的物品，直接识别
                    if (!result.isSample)
                    {
                        result.code = heheOcr.Recognize(result.filePath, (int)ImageShapeEnum.RECTANGLE);
                    }

                    if (receiveOCRResult != null)
                    {
                        receiveOCRResult.Invoke(result);
                    }
                }
                if (updateResultDelegate != null)
                {
                    updateResultDelegate.Invoke(result);
                }
               
                Console.WriteLine("{0} OCR识别完成，结果：{1},用时：{2}, filePath={3}",
                    DateTime.Now, result.code, DateTime.Now - startTime, result.filePath);
            }
            catch (Exception ex)
            {
                Console.WriteLine("OCR识别时发生异常：{0} {1}", ex.Message, ex.StackTrace);
                result.code = "ERROR";
            }
        }*/

        /// <summary>
        /// 再次拉直
        /// </summary>
        /// <param name="data"></param>
        public static void OCRReWork(OCRResult result)
        {
            if (result != null)
            {
                Console.WriteLine("再次拉直");
                result.status = 2;
                OCRWork(result);
            }
        }

        /// <summary>
        /// 再次处理
        /// </summary>
        /// <param name="result"></param>
        public static void OCRRedo(OCRResult result)
        {
            if (result != null)
            {
                Console.WriteLine("再次拉直");
                result.status = 3;
                OCRAndStraightService.ocrTotalCount = 1;
                OCRWork(result);
            }
        }

        /// <summary>
        /// 清空数据
        /// </summary>
        public static void ClearData()
        {
            rowNum = 0;
            OCRDataList.Clear();
            OCRDataDic.Clear();
        }

        public static void generatCaptureOptSN()
        {
         captureOptSN = Eps.Ai.Common.Config.UPPER_DEVICE_NO+DateTime.Now.ToString("yyMMddHHmmss");
        }
    }
}
